package com.example.singletask

import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.singletask.util.SingleTask
import com.example.singletask.util.Task
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class SingleTaskTest {

    @Test
    fun normalityTest(){
        var testResult = false

        val task = Task.singleTask {task ->
            var result = 0
            while (task.isRunning){
                result++
                Thread.sleep(100)

                println("${Thread.currentThread()} do, $result")
                if (result > 10)
                    break
            }
            return@singleTask result
        }.success { res ->
            println("${Thread.currentThread()} success, $res")
            testResult = true
        }.error { err ->
            println("${Thread.currentThread()} error, $err")
        }.interrupted {
            println("${Thread.currentThread()} interrupted")
        }

        task.start()
        Thread.sleep(2000)

        Assert.assertTrue(testResult)
    }

    @Test
    fun cancelTest(){
        var testResult = false

        val task = Task.singleTask{ task ->
            var result = 0
            while (task.isRunning) {
                result++
                Thread.sleep(100)

                println("${Thread.currentThread()} do, $result")
                if (result > 10)
                    break
            }
            return@singleTask result
        }.success { res ->
            println("${Thread.currentThread()} success, $res")
        }.error { err ->
            println("${Thread.currentThread()} error, $err")
        }.interrupted {
            println("${Thread.currentThread()} interrupted")
            testResult = true
        }

        task.start()
        Thread.sleep(500)
        task.cancel()
        Thread.sleep(500)

        Assert.assertTrue(testResult)
    }

    @Test
    fun errorTest(){
        var testResult = false

        val task = Task.singleTask{ task ->
            var result = 0
            while (task.isRunning) {
                result++
                Thread.sleep(100)
                println("${Thread.currentThread()} do, $result")

                if (result > 5) throw InterruptedException("throw error")

                if (result > 10)
                    break
            }
            return@singleTask result
        }.success { res ->
            println("${Thread.currentThread()} success, $res")
        }.error { err ->
            println("${Thread.currentThread()} error, $err")
            testResult = true
        }.interrupted {
            println("${Thread.currentThread()} interrupted")
            testResult = true
        }

        task.start()
        Thread.sleep(2000)

        Assert.assertTrue(testResult)
    }

    @Test
    fun implementTest(){
        var testResult = false

        val task = CountTask()
            .success { res ->
                println("${Thread.currentThread()} success, $res")
                testResult = true
            }.error { err ->
                println("${Thread.currentThread()} error, $err")
            }.interrupted {
                println("${Thread.currentThread()} interrupted")
            }

        task.start()
        Thread.sleep(1500)

        Assert.assertTrue(testResult)
    }

    @Test
    fun restart(){
        var testResult = false

        val task = Task.singleTask{ task ->
            var result = 0
            while (task.isRunning) {
                result++
                Thread.sleep(100)

                println("${Thread.currentThread()} do, $result")
                if (result > 10)
                    break
            }
            return@singleTask result
        }.success { res ->
            println("${Thread.currentThread()} success, $res")
            testResult = true
        }.error { err ->
            println("${Thread.currentThread()} error, $err")
        }.interrupted {
            println("${Thread.currentThread()} interrupted")
        }

        task.start()
        Thread.sleep(500)
        task.cancel()
        println("restart")
        task.start()
        Thread.sleep(5000)

        Assert.assertTrue(testResult)
    }

    class CountTask : SingleTask<Unit>(){
        override fun onTaskRun() {
            var result = 0
            while (isRunning) {
                result++
                Thread.sleep(100)

                println("${Thread.currentThread()} do, $result")
                if (result > 10)
                    break
            }
        }
    }
}